package cn.fintecher.pangolin.service.repair.web;

import cn.fintecher.pangolin.common.enums.ApplyFileContent;
import cn.fintecher.pangolin.common.enums.ManagementType;
import cn.fintecher.pangolin.common.exception.BadRequestException;
import cn.fintecher.pangolin.common.model.OperatorModel;
import cn.fintecher.pangolin.common.model.RepairFileModel;
import cn.fintecher.pangolin.common.model.UnZipFileModel;
import cn.fintecher.pangolin.common.model.UserModel;
import cn.fintecher.pangolin.common.utils.Constants;
import cn.fintecher.pangolin.common.utils.ZWDateUtil;
import cn.fintecher.pangolin.entity.elastic.DataRepairImportRecord;
import cn.fintecher.pangolin.entity.mysql.SysParam;
import cn.fintecher.pangolin.service.repair.client.SysParamClient;
import cn.fintecher.pangolin.service.repair.model.request.DataRepairImportRequest;
import cn.fintecher.pangolin.service.repair.respository.DataRepairImportRespository;
import cn.fintecher.pangolin.service.repair.service.DataRepairBaseService;
import cn.fintecher.pangolin.service.repair.service.DataRepairImportService;
import cn.fintecher.pangolin.service.repair.service.UploadFileService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.*;


/**
 * Created by hanwannan on 2017/9/1.
 */
@RestController
@RequestMapping("/api/dataRepairImport")
@Api(value = "数据修复资料导入", description = "数据修复资料导入")
public class DataRepairImportController {
    private final Logger log = LoggerFactory.getLogger(DataRepairImportController.class);

    @Autowired
    private DataRepairImportRespository dataRepairImportRespository;

    @Autowired
    DataRepairImportService dataRepairImportService;

    @Autowired
    DataRepairBaseService dataRepairBaseService;

    @Autowired
    SysParamClient sysParamClient;

    @Autowired
    ElasticsearchTemplate elasticsearchTemplate;

    @Autowired
    UploadFileService uploadFileService;

    @PostMapping("/import")
    @ApiOperation(value = "资料导入", notes = "资料导入")
    public ResponseEntity importData(@Valid @RequestBody DataRepairImportRequest request,
                                     @RequestHeader(value = "X-UserToken") @ApiParam("操作者的Token") String token) {
        List<String> errorList = new ArrayList<>();
        try {
            //获取用户信息
            UserModel operator = dataRepairBaseService.getUserByToken(token);
            //获取文件
            String fileId;
            RepairFileModel repairFileModel = null;
            try {
                if (Objects.equals(request.getHasPicture(), ManagementType.YES)) {
                    UnZipFileModel model = new UnZipFileModel();
                    model.setFileId(request.getFileId());
                    model.setType(request.getImportContentType());
                    repairFileModel = uploadFileService.unZipCaseFile(model);
                    fileId = repairFileModel.getExcelFile().getId();
                } else {
                    fileId = request.getFileId();
                }
            } catch (Exception e) {
                throw new Exception("file.is.illegal");
            }
            InputStream inputStream = new FileInputStream(uploadFileService.findOneFileById(fileId));

            //数据库添加导入记录
            DataRepairImportRecord dataRepairImportRecord = new DataRepairImportRecord();
            dataRepairImportRecord.setFileId(request.getFileId());
            dataRepairImportRecord.setOperatorTime(ZWDateUtil.getNowDateTime());
            dataRepairImportRecord.setOperatorName(operator.getRealName());
            dataRepairImportRecord.setOperatorUserName(operator.getUsername());
            dataRepairImportRecord.setImportContentType(request.getImportContentType());
            dataRepairImportRespository.save(dataRepairImportRecord);
            //数据导入
            dataRepairImportService.importExcelData(request, inputStream, errorList, repairFileModel);
            if (errorList.size() > 0) {
                return ResponseEntity.ok().body(errorList);
            }
            return ResponseEntity.ok().body(null);
        } catch (final Exception e) {
            log.error(e.getMessage(), e);
            throw new BadRequestException(null, "importExcelData", Objects.isNull(e.getMessage()) ? "importExcelData.is.fail" : e.getMessage());

        }
    }

    @PostMapping("/importCompare")
    @ApiOperation(value = "导入比较", notes = "导入比较")
    public ResponseEntity importCompare(@Valid @RequestBody DataRepairImportRequest request,
                                        @RequestHeader(value = "X-UserToken") @ApiParam("操作者的Token") String token) throws Exception {
        log.info("导入比较");
        UserModel operator = dataRepairBaseService.getUserByToken(token);
        String fileId = request.getFileId();
        InputStream inputStream = new FileInputStream(uploadFileService.findOneFileById(fileId));
        dataRepairImportService.importCompare(request, inputStream, operator);
        return ResponseEntity.ok().body(null);
    }

    @GetMapping("/getDataTypes")
    @ApiOperation(value = "获取数据类型", notes = "获取数据类型")
    public ResponseEntity<Set<String>> getDataTypes(@RequestParam ApplyFileContent importType) {
        String indexName;
        if (Objects.equals(importType, ApplyFileContent.PHONE_RESOURCE)) {
            indexName = "communication_data";
        } else if (Objects.equals(importType, ApplyFileContent.SPECIAL_RESOURCE)) {
            indexName = "special_transfer_data";
        } else if (Objects.equals(importType, ApplyFileContent.HOUSEHOLD_REGISTER_REMARK)) {
            indexName = "koseki_remark";
        } else {
            return ResponseEntity.ok().body(null);
        }
        Set<String> resList = new HashSet<>();
        TermsAggregationBuilder aggregationBuilder = AggregationBuilders
                //分组别名/分组字段
                .terms("type").field("type.keyword")
                .size(10000);
        SearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withIndices(indexName)
                .withTypes(indexName)
                .withSearchType(SearchType.DEFAULT)
                .addAggregation(aggregationBuilder).build();
        Aggregations aggregations = elasticsearchTemplate.query(searchQuery, response -> response.getAggregations());
        Terms stringTerms = aggregations.get("type");
        stringTerms.getBuckets().forEach(bucket -> resList.add(bucket.getKey().toString()));
        return ResponseEntity.ok().body(resList);
    }

    @GetMapping("/getSystemTemplate")
    @ApiOperation(value = "获取默认导入模板", notes = "获取默认导入模板")
    public ResponseEntity<SysParam> getSystemTemplate(@RequestParam ApplyFileContent applyFileContent) {
        log.info("REST request to getSystemTemplate");
        String code;
        SysParam result = null;
        try {
            switch (applyFileContent) {
                case HOUSEHOLD_REGISTER_RESOURCE:
                    code = Constants.HOUSEHOLD_REGISTER_RESOURCE;
                    break;
                case HOUSEHOLD_REGISTER_REMARK:
                    code = Constants.HOUSEHOLD_REGISTER_REMARK;
                    break;
                case CONTACT_RELATIONSHIP:
                    code = Constants.CONTACT_RELATIONSHIP;
                    break;
                case SOCIAL_SECURITY:
                    code = Constants.SOCIAL_SECURITY;
                    break;
                case TOWN_RESOURCE:
                    code = Constants.TOWN_RESOURCE;
                    break;
                case PHONE_RESOURCE:
                    code = Constants.PHONE_RESOURCE;
                    break;
                case SPECIAL_RESOURCE:
                    code = Constants.SPECIAL_RESOURCE;
                    break;
                default:
                    throw new Exception("templateType.is.error");
            }
            ResponseEntity<SysParam> entity = sysParamClient.querySysParamByCode(code);
            if (Objects.nonNull(entity) && Objects.nonNull(entity.getBody())) {
                result = entity.getBody();
            }
            return ResponseEntity.ok().body(result);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new BadRequestException(null, "getCaseInfoProperty", Objects.isNull(e.getMessage()) ? "getCaseInfoProperty.is.fail" : e.getMessage());
        }
    }
}
